﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using Honest.MES.Contracts.Attributes;
using Honest.MES.Contracts.Events;
using Honest.MES.Contracts.Interfaces;

namespace Honest.MES.Contracts.Services
{
    public class ModuleDiscoveryService : IModuleDiscoveryService
    {
        public event EventHandler<ModulesDiscoveredEventArgs> ModulesDiscovered;

        public IEnumerable<Type> DiscoverModules()
        {
            var modules = new List<Type>();

            try
            {
                foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
                {
                    try
                    {
                        modules.AddRange(DiscoverModulesFromAssembly(assembly));
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine($"从程序集 {assembly.FullName} 发现模块时出错: {ex.Message}");
                    }
                }

                var modulesPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules");
                if (Directory.Exists(modulesPath))
                {
                    modules.AddRange(DiscoverModulesFromDirectory(modulesPath));
                }

                ModulesDiscovered?.Invoke(this, new ModulesDiscoveredEventArgs(modules.Distinct()));
                return modules.Distinct();
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"发现模块时发生错误: {ex.Message}");
                return Enumerable.Empty<Type>();
            }
        }

        public IEnumerable<Type> DiscoverModulesFromAssembly(Assembly assembly)
        {
            var modules = new List<Type>();

            try
            {
                if (assembly.FullName.StartsWith("System.") ||
                    assembly.FullName.StartsWith("Microsoft.") ||
                    assembly.FullName.StartsWith("Prism.") ||
                    assembly.FullName.StartsWith("WindowsBase."))
                {
                    return modules;
                }

                foreach (var type in assembly.GetTypes())
                {
                    try
                    {
                        var attribute = type.GetCustomAttribute<ModelInfoAttribute>();
                        if (attribute != null)
                        {
                            modules.Add(type);
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine($"检查类型 {type.Name} 时出错: {ex.Message}");
                    }
                }
            }
            catch (ReflectionTypeLoadException ex)
            {
                foreach (var type in ex.Types)
                {
                    if (type != null)
                    {
                        try
                        {
                            var attribute = type.GetCustomAttribute<ModelInfoAttribute>();
                            if (attribute != null)
                            {
                                modules.Add(type);
                            }
                        }
                        catch
                        {
                            // 忽略无法检查的类型
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"从程序集 {assembly.FullName} 发现模块时出错: {ex.Message}");
            }

            return modules;
        }

        public IEnumerable<Type> DiscoverModulesFromDirectory(string directoryPath)
        {
            var modules = new List<Type>();

            if (!Directory.Exists(directoryPath))
            {
                Debug.WriteLine($"模块目录不存在: {directoryPath}");
                return modules;
            }

            foreach (var file in Directory.GetFiles(directoryPath, "*.dll"))
            {
                try
                {
                    var assembly = Assembly.LoadFrom(file);

                    if (assembly.FullName.StartsWith("System.") ||
                        assembly.FullName.StartsWith("Microsoft.") ||
                        assembly.FullName.StartsWith("Prism."))
                    {
                        continue;
                    }

                    modules.AddRange(DiscoverModulesFromAssembly(assembly));
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"加载程序集 {file} 失败: {ex.Message}");
                }
            }

            return modules;
        }

        public ModelInfoAttribute DiscoverModuleInfo(Type moduleType)
        {
            if (moduleType == null)
                throw new ArgumentNullException(nameof(moduleType));

            return moduleType.GetCustomAttribute<ModelInfoAttribute>();
        }
    }
}